package com.zlzlib.libnetty.tcp;

import com.zlzlib.libnetty.base.BaseClient;
import com.zlzlib.libnetty.tcp.handler.HeartbeatHandler;
import com.zlzlib.libnetty.util.Util;

import java.net.URI;
import java.util.concurrent.TimeUnit;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * tcp连接的客户端
 *
 * @DateTime: 2021/4/23 10:35
 * @Author zlz
 * @Version 1.0
 */
public class TCPClient<T> extends BaseClient<T> {

    @Override
    protected void initChannel() {
        ChannelHandler channelHandler = null;
        if (mEventListener != null) {
            channelHandler = mEventListener.getTcpChannel(this);
        }
        if (channelHandler != null) {
            bootstrap.handler(channelHandler);
        } else {
            bootstrap.handler(new TCPChannelInitializer<>(this));
        }
    }

    @Override
    protected void initChannel(URI url) {

    }

    @Override
    protected void toServer() {
        try {
            channel = (SocketChannel) bootstrap.connect(currentHost, currentPort).sync().channel();
        } catch (Exception e) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            Util.logError(String.format("连接Server(ip[%s], port[%s])失败%n", currentHost, currentPort));
            channel = null;
        }
    }

    @Override
    protected void sendSelfMsg(final T msg) {
        try {
            ChannelFuture future = channel.writeAndFlush(msg);
            future.addListener((ChannelFutureListener) channelFuture -> {
                Util.logInfo("发送消息，message=" + msg + "  " + channelFuture.isSuccess());
                mEventListener.msgSendState(msg, channelFuture.isSuccess());
            });
        } catch (Exception ex) {
            Util.logInfo("发送消息失败，reason:" + ex.getMessage() + "\tmessage=" + msg);
            mEventListener.msgSendState(msg, false);
        }
    }

    @Override
    protected void startHandshake() {
        T handshakeMsg = getDataListener().getHandshakeMsg();
        Util.logInfo("握手消息，message=" + handshakeMsg);
        if (handshakeMsg != null) {
            sendMsg(handshakeMsg, false);
        } else {
            //无握手信息直接开启心跳
            addHeartbeatHandler();
        }
    }

    @Override
    public void addHeartbeatHandler() {
        if (channel == null || !channel.isActive() || channel.pipeline() == null) {
            return;
        }
        try {
            // 之前存在的读写超时handler，先移除掉，再重新添加
            if (channel.pipeline().get(IdleStateHandler.class.getSimpleName()) != null) {
                channel.pipeline().remove(IdleStateHandler.class.getSimpleName());
            }
            if (channel.pipeline().get(HeartbeatHandler.class.getSimpleName()) != null) {
                channel.pipeline().remove(HeartbeatHandler.class.getSimpleName());
            }
            // 3次心跳没响应，代表连接已断开
            channel.pipeline().addFirst(IdleStateHandler.class.getSimpleName(), new IdleStateHandler(
                    3L * getHeartbeatInterval(), getHeartbeatInterval(), 0, TimeUnit.MILLISECONDS));
            // 重新添加HeartbeatHandler
            channel.pipeline().addLast(HeartbeatHandler.class.getSimpleName(), new HeartbeatHandler<>(this));
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("添加心跳消息管理handler失败，reason：" + e.getMessage());
        }
    }
}
